package com.zhuiwei.initialization;

import static net.mindview.util.Print.*;

/**
 * 静态数据初始化
 * @author zhuiwei
 * @see 《java编程思想 第四版》5.7.2
 */
class Bowl {
  Bowl(int marker) {
    print("Bowl(" + marker + ")");
  }
  void f1(int marker) {
    print("f1(" + marker + ")");
  }
}

class Table {
  static Bowl bowl1 = new Bowl(1); //①
  Table() {
    print("Table()");
    bowl2.f1(1);
  }
  void f2(int marker) {
    print("f2(" + marker + ")");
  }
  static Bowl bowl2 = new Bowl(2);//②
}

class Cupboard {
  Bowl bowl3 = new Bowl(3); //③
  static Bowl bowl4 = new Bowl(4); //④
  Cupboard() {
    print("Cupboard()");
    bowl4.f1(2);
  }
  void f3(int marker) {
    print("f3(" + marker + ")");
  }
  static Bowl bowl5 = new Bowl(5); //⑤
}

public class StaticInitialization {
  public static void main(String[] args) {
    print("Creating new Cupboard() in main");
    new Cupboard();
    print("Creating new Cupboard() in main");
    new Cupboard();

    table.f2(1);
    cupboard.f3(1);
  }
  static Table table = new Table();
  static Cupboard cupboard = new Cupboard();
}

/*
输出结果:
Bowl(1)
Bowl(2)
Table()
f1(1)
Bowl(4)
Bowl(5)
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
Creating new Cupboard() in main
Bowl(3)
Cupboard()
f1(2)
f2(1)
f3(1)
*/
/**
 * 说明:
 * 调用方法或初始化会先加载类；
 * 类被加载时，自动对变量初始化。初始化顺序：静态数据、非静态数据、构造器；
 * 静态数据只被初始化一次，初始化后不会再次初始化
 * static关键字不能用于局部变量
 * 本例：
 * 1、调用静态main()方法，需要加载对应的类StaticInitialization并初始化变量，静态域table和cupboard会被初始化，同时对应的类也被加载。
 *                                          static Table table = new Table();
 *                                          static Cupboard cupboard = new Cupboard();
 * 2、Table类被加载，初始化变量先静态后构造器：先初始化①，输出Bowl(1); 在初始化②，输出Bowl(2); 执行构造器，输出Table()，f1(1)
 * 3、Cupboard类被加载，初始化顺序静态对象、非静态对象、构造器：
 *                                            初始化④，输出Bowl(4);初始化⑤，输出Bowl(5);初始化③，输出输出Bowl(3);执行构造器，输出Cupboard() f1(2)
 * 4、执行 print("Creating new Cupboard() in main"); 对应输出
 * 5、执行 new Cupboard();
 *                       初始化③，输出Bowl(3)；执行构造器，输出Cupboard() f1(2)；
 *                       说明：此处不初始化④和⑤，原因静态数据初始化只执行一次；
 * 6、print("Creating new Cupboard() in main");对应输出
 * 7、new Cupboard();
 *                   初始化③，输出Bowl(3)；执行构造器，输出Cupboard() f1(2)；
 *                   说明：此处不初始化④和⑤，原因静态数据初始化只执行一次；
 * 8、执行 table.f2(1); 静态对象已经初始化，在调用时不需要初始化输出f2(1)
 * 9、执行cupboard.f3(1); 静态对象已经初始化，在调用时不需要初始化输出f3(1)
 */
